/**
 * Copyright (c) 快宝网络 kuaidihelp.com Co., Ltd. All Rights Reserved 禁止外泄以及用于其它的商业用途
 */

import { debounce } from 'lodash';
import { useEffect, useRef } from 'react';
import type { Location } from 'umi';
import { useLocation, useModel } from 'umi';

export type WinSize = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
export type WinSizeCallback = (p: { size: number; winSize: WinSize }) => void;
export const winSizeMap = {
  xxl: 1600,
  xl: 1200,
  lg: 992,
  md: 768,
  sm: 576,
  xs: 480,
};
// 按照antd.Grid组件分类
const formatWinSizes: WinSize[] = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
const formatWinSize = (w: number): WinSize => {
  if (w >= winSizeMap.xxl) return 'xxl';
  if (w >= winSizeMap.xl) return 'xl';
  if (w >= winSizeMap.lg) return 'lg';
  if (w >= winSizeMap.md) return 'md';
  if (w >= winSizeMap.sm) return 'sm';
  return 'xs';
};

export function useWindowSizeChange(callback?: WinSizeCallback) {
  const { setInitialState } = useModel('@@initialState');

  useEffect(() => {
    const setWindowSize = debounce(
      () => {
        const size = document.documentElement.clientWidth;
        const winSize = formatWinSize(size);
        setInitialState((preInitialState) => ({
          ...preInitialState,
          winSize,
        }));
        if (callback) {
          callback({ size, winSize });
        }
      },
      300,
      { leading: false, trailing: true },
    );
    setWindowSize();
    window.addEventListener('resize', setWindowSize);
    return () => {
      window.removeEventListener('resize', setWindowSize);
    };
  }, []);
}

/**
 *
 * @descriptions 比较窗口大小 hopeWinSize:xs
 * @param hopeWinSize
 * @param fix 增加尺寸
 * @returns
 */
export function compareWindowSize(hopeWinSize: WinSize, fix?: number): number {
  let hopeSize = winSizeMap[hopeWinSize];
  if (fix) {
    // 补充尺寸
    hopeSize = hopeSize + fix;
  }
  const currentSize = document.documentElement.clientWidth;
  if (hopeSize > currentSize) return 1;
  if (hopeSize < currentSize) return -1;
  return 0;
}

/**
 *
 * @descriptions 比较窗口尺寸是否符合预期
 * @param hopeWinSize 期望的尺寸
 * @param exact_ 是否严格匹配
 * @returns boolean
 */
export function useCompareWindowSize(
  hopeWinSize?: WinSize | WinSize[],
  exact_: boolean = false,
): boolean {
  const { initialState } = useModel('@@initialState');
  const { winSize } = initialState || {};
  if (!winSize || !hopeWinSize) return false;
  let hopeWinSizes = hopeWinSize;
  let exact = true; // hopeWinSize非字符串则强制严格匹配
  if (typeof hopeWinSize === 'string') {
    hopeWinSizes = [hopeWinSize];
    exact = exact_;
  }
  if (exact) {
    return hopeWinSizes.includes(winSize);
  }
  const winSizeIndex = formatWinSizes.findIndex((item) => item === winSize);
  const hopeWinSizeIndex = formatWinSizes.findIndex((item) => item === hopeWinSize);
  return hopeWinSizeIndex <= winSizeIndex;
}

/**
 *
 * @description 路径变化记录滚动，下次进入恢复滚动位置
 */
interface ScrollMap {
  [key: string]: number;
}
interface ScrollViewRef {
  scrollMap: ScrollMap;
  pathname: string;
}
export function useResetScrollView() {
  const location: Location = useLocation();
  const { pathname } = location;
  const scrollViewRef = useRef<ScrollViewRef>({
    scrollMap: {},
    pathname,
  });

  // 记录滚动位置
  const recordCurrentScroll = (_pathname: string) => {
    scrollViewRef.current.scrollMap[_pathname] = document.documentElement.scrollTop;
  };

  // 滚动到指定位置
  const scrollIntoRecord = (_pathname: string) => {
    const scrollTop = scrollViewRef.current.scrollMap[_pathname] || 0;
    document.documentElement.scrollTop = scrollTop;
  };

  useEffect(() => {
    const listenerHandler = () => recordCurrentScroll(scrollViewRef.current.pathname);
    window.addEventListener('scroll', listenerHandler);
    return () => {
      window.removeEventListener('scroll', listenerHandler);
    };
  }, []);

  useEffect(() => {
    scrollViewRef.current.pathname = pathname;
    scrollIntoRecord(pathname);
  }, [pathname]);
}
